﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using LibEBML.Common;
using VBFOOL.MediaPlayer.Core;
using VBFOOL.MediaPlayer.Core.Interface;
namespace VBFOOL.MediaPlayer.MKV
{

    class MKVMediaStream : IMediaStream
    {
        internal MKVMediaStream(MKVFileSource source)
        {
            m_source = source;
        }

        MKVFileSource m_source;

        public IInputSource Source { get { return m_source; } }

        //internal void Seek(int ClusterIndex, int BlockIndex)
        //{
        //    FrameQueue.Clear();

        //    CurrentStep.ClusterIndex = ClusterIndex;
        //    CurrentStep.BlockIndex = BlockIndex;
        //    FillVideoQueue();
        //}

        internal void SetTrack(MKVMediaTrack track)
        {
            m_Track = track;
        }
        MKVMediaTrack m_Track = null;

        public IMediaTrack CurrentTrack { get { return m_Track; } }

        Queue<FrameData> FrameQueue = new Queue<FrameData>();

        internal event EventHandler FillQueue;

        internal void ClearQueue()
        {
            lock (FrameQueue)
            {
                FrameQueue.Clear();
            }
        }

        internal int FrameCount
        {
            get
            {
                lock (FrameQueue)
                {
                    return FrameQueue.Count;
                }
            }
        }

        internal void Enqueue(Cluster curcluster, SimpleBlock curblock)
        {
            if (state < 0)
            {
                return;
            }
            if (curcluster != null)
            {
                long lp = curcluster.TimeCode + curblock.TimeCode;
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                long p = 0, mt = 0, pc = m_Track.DefaultDuration;
                var dts = curblock.GetBlockData(m_Track.CompressHeader);
                if (curblock is Block)
                {
                    var bs = curblock as Block;
                    if (bs.BlockDuration > 0)
                    {
                        pc = bs.BlockDuration * m_Track.TimeCodeScale;
                    }
                }
                foreach (var item1 in dts)
                {
                    try
                    {
                        var b = m_Track.Codec.Translate(item1, 0, item1.Length);
                        ms.Write(b, 0, b.Length);
                        FrameData fd = new FrameData();
                        fd.TimeCode = lp * m_Track.TimeCodeScale + mt;
                        fd.Data = ms;
                        fd.Position = p;
                        p += b.Length;
                        fd.Duration = pc;
                        fd.Length = b.Length;
                        lock (FrameQueue)
                        {
                            FrameQueue.Enqueue(fd);
                        }
                        mt += pc;
                    }
                    catch (Exception)
                    {

                     //   throw;
                    }
                }
            }
            else
            {
                state = -1;
                FrameData fd = new FrameData();
                lock (FrameQueue)
                {
                    FrameQueue.Enqueue(fd);
                }
            }
        }


        public double BufferProgress
        {
            get
            {
                if (FrameQueue.Count > 0)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }
        internal int state = 0;
        public FrameData GetFrame()
        {
            try
            {
                FrameData item = null;
                lock (FrameQueue)
                {
                    item = FrameQueue.Dequeue();
                }
                return item;
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}